home *** CD-ROM | disk | FTP | other *** search
- /* source/creature.c: handle monster movement and attacks
-
- Copyright (c) 1989-92 James E. Wilson, Robert A. Koeneke
-
- This software may be copied and distributed for educational, research, and
- not for profit purposes provided that this copyright and statement are
- included in all such copies. */
-
- #ifdef __TURBOC__
- #include <stdio.h>
- #include <stdlib.h>
- #endif /* __TURBOC__ */
-
- #include "config.h"
- #include "constant.h"
- #include "types.h"
- #include "externs.h"
-
- #ifdef USG
- #ifndef ATARIST_MWC
- #include <string.h>
- #else
- char *strcat();
- char *strcpy();
- #endif
- #else
- #include <strings.h>
- #endif
-
- #if defined(LINT_ARGS)
- static int movement_rate(int16);
- static int check_mon_lite(int, int);
- static void get_moves(int, int *);
- static void make_attack(int);
- static void make_move(int, int *, int32u *);
- static void mon_cast_spell(int, int *);
- static void mon_move(int, int32u *);
- #endif
-
- #ifdef ATARIST_TC
- /* Include this to get prototypes for standard library functions. */
- #include <stdlib.h>
- #endif
-
-
- /* Updates screen when monsters move about -RAK- */
- void update_mon(monptr)
- int monptr;
- {
- register int flag;
- register cave_type *c_ptr;
- register monster_type *m_ptr;
- register creature_type *r_ptr;
- #ifdef ATARIST_MWC
- int32u holder;
- #endif
-
- m_ptr = &m_list[monptr];
- flag = FALSE;
- if ((m_ptr->cdis <= MAX_SIGHT) &&
- !(py.flags.status & PY_BLIND) &&
- (panel_contains((int)m_ptr->fy, (int)m_ptr->fx)))
- {
- /* Wizard sight. */
- if (wizard)
- flag = TRUE;
- /* Normal sight. */
- else if (los(char_row, char_col, (int)m_ptr->fy, (int)m_ptr->fx))
- {
- c_ptr = &cave[m_ptr->fy][m_ptr->fx];
- r_ptr = &c_list[m_ptr->mptr];
- if (c_ptr->pl || c_ptr->tl ||
- (find_flag && m_ptr->cdis < 2 && player_light))
- {
- #ifdef ATARIST_MWC
- holder = CM_INVISIBLE;
- if ((holder & r_ptr->cmove) == 0)
- #else
- if ((CM_INVISIBLE & r_ptr->cmove) == 0)
- #endif
- flag = TRUE;
- else if (py.flags.see_inv)
- {
- flag = TRUE;
- #ifdef ATARIST_MWC
- c_recall[m_ptr->mptr].r_cmove |= holder;
- #else
- c_recall[m_ptr->mptr].r_cmove |= CM_INVISIBLE;
- #endif
- }
- }
- /* Infra vision. */
- else if ((py.flags.see_infra > 0) &&
- (m_ptr->cdis <= py.flags.see_infra) &&
- (CD_INFRA & r_ptr->cdefense))
- {
- flag = TRUE;
- c_recall[m_ptr->mptr].r_cdefense |= CD_INFRA;
- }
- }
- }
- /* Light it up. */
- if (flag)
- {
- if (!m_ptr->ml)
- {
- disturb (1, 0);
- m_ptr->ml = TRUE;
- lite_spot((int)m_ptr->fy, (int)m_ptr->fx);
- screen_change = TRUE; /* notify inven_command */
- }
- }
- /* Turn it off. */
- else if (m_ptr->ml)
- {
- m_ptr->ml = FALSE;
- lite_spot((int)m_ptr->fy, (int)m_ptr->fx);
- screen_change = TRUE; /* notify inven_command */
- }
- }
-
-
- /* Given speed, returns number of moves this turn. -RAK- */
- /* NOTE: Player must always move at least once per iteration, */
- /* a slowed player is handled by moving monsters faster */
- static int movement_rate(speed)
- register int16 speed;
- {
- if (speed > 0)
- {
- if (py.flags.rest != 0)
- return 1;
- else
- return speed;
- }
- else
- {
- /* speed must be negative here */
- return ((turn % (2 - speed)) == 0);
- }
- }
-
-
- /* Makes sure a new creature gets lit up. -CJS- */
- static int check_mon_lite(y, x)
- int y, x;
- {
- register int monptr;
-
- monptr = cave[y][x].cptr;
- if (monptr <= 1)
- return FALSE;
- else
- {
- update_mon(monptr);
- return m_list[monptr].ml;
- }
- }
-
-
- /* Choose correct directions for monster movement -RAK- */
- static void get_moves(monptr, mm)
- int monptr;
- register int *mm;
- {
- int y, ay, x, ax, move_val;
-
- y = m_list[monptr].fy - char_row;
- x = m_list[monptr].fx - char_col;
- if (y < 0)
- {
- move_val = 8;
- ay = -y;
- }
- else
- {
- move_val = 0;
- ay = y;
- }
- if (x > 0)
- {
- move_val += 4;
- ax = x;
- }
- else
- ax = -x;
- /* this has the advantage of preventing the diamond maneuvre, also faster */
- if (ay > (ax << 1))
- move_val += 2;
- else if (ax > (ay << 1))
- move_val++;
- switch(move_val)
- {
- case 0:
- mm[0] = 9;
- if (ay > ax)
- {
- mm[1] = 8;
- mm[2] = 6;
- mm[3] = 7;
- mm[4] = 3;
- }
- else
- {
- mm[1] = 6;
- mm[2] = 8;
- mm[3] = 3;
- mm[4] = 7;
- }
- break;
- case 1: case 9:
- mm[0] = 6;
- if (y < 0)
- {
- mm[1] = 3;
- mm[2] = 9;
- mm[3] = 2;
- mm[4] = 8;
- }
- else
- {
- mm[1] = 9;
- mm[2] = 3;
- mm[3] = 8;
- mm[4] = 2;
- }
- break;
- case 2: case 6:
- mm[0] = 8;
- if (x < 0)
- {
- mm[1] = 9;
- mm[2] = 7;
- mm[3] = 6;
- mm[4] = 4;
- }
- else
- {
- mm[1] = 7;
- mm[2] = 9;
- mm[3] = 4;
- mm[4] = 6;
- }
- break;
- case 4:
- mm[0] = 7;
- if (ay > ax)
- {
- mm[1] = 8;
- mm[2] = 4;
- mm[3] = 9;
- mm[4] = 1;
- }
- else
- {
- mm[1] = 4;
- mm[2] = 8;
- mm[3] = 1;
- mm[4] = 9;
- }
- break;
- case 5: case 13:
- mm[0] = 4;
- if (y < 0)
- {
- mm[1] = 1;
- mm[2] = 7;
- mm[3] = 2;
- mm[4] = 8;
- }
- else
- {
- mm[1] = 7;
- mm[2] = 1;
- mm[3] = 8;
- mm[4] = 2;
- }
- break;
- case 8:
- mm[0] = 3;
- if (ay > ax)
- {
- mm[1] = 2;
- mm[2] = 6;
- mm[3] = 1;
- mm[4] = 9;
- }
- else
- {
- mm[1] = 6;
- mm[2] = 2;
- mm[3] = 9;
- mm[4] = 1;
- }
- break;
- case 10: case 14:
- mm[0] = 2;
- if (x < 0)
- {
- mm[1] = 3;
- mm[2] = 1;
- mm[3] = 6;
- mm[4] = 4;
- }
- else
- {
- mm[1] = 1;
- mm[2] = 3;
- mm[3] = 4;
- mm[4] = 6;
- }
- break;
- case 12:
- mm[0] = 1;
- if (ay > ax)
- {
- mm[1] = 2;
- mm[2] = 4;
- mm[3] = 3;
- mm[4] = 7;
- }
- else
- {
- mm[1] = 4;
- mm[2] = 2;
- mm[3] = 7;
- mm[4] = 3;
- }
- break;
- }
- }
-
-
- /* Make an attack on the player (chuckle.) -RAK- */
- static void make_attack(monptr)
- int monptr;
- {
- int attype, adesc, adice, asides;
- int i, j, damage, flag, attackn, notice, visible;
- int32 gold;
- int8u *attstr;
- vtype cdesc, tmp_str, ddesc;
- register creature_type *r_ptr;
- monster_type *m_ptr;
- register struct misc *p_ptr;
- register struct flags *f_ptr;
- register inven_type *i_ptr;
- #ifdef ATARIST_MWC
- int32u holder;
- #endif
-
- if (death) /* don't beat a dead body! */
- return;
-
- m_ptr = &m_list[monptr];
- r_ptr = &c_list[m_ptr->mptr];
- if (!m_ptr->ml)
- (void) strcpy(cdesc, "It ");
- else
- (void) sprintf(cdesc, "The %s ", r_ptr->name);
- /* For "DIED_FROM" string */
- #ifdef ATARIST_MWC
- holder = CM_WIN;
- if (holder & r_ptr->cmove)
- #else
- if (CM_WIN & r_ptr->cmove)
- #endif
- (void) sprintf(ddesc, "The %s", r_ptr->name);
- else if (is_a_vowel (r_ptr->name[0]))
- (void) sprintf(ddesc, "an %s", r_ptr->name);
- else
- (void) sprintf (ddesc, "a %s", r_ptr->name);
- /* End DIED_FROM */
-
- attackn = 0;
- attstr = r_ptr->damage;
- while ((*attstr != 0) && !death)
- {
- attype = monster_attacks[*attstr].attack_type;
- adesc = monster_attacks[*attstr].attack_desc;
- adice = monster_attacks[*attstr].attack_dice;
- asides = monster_attacks[*attstr].attack_sides;
- attstr++;
- flag = FALSE;
- if ((py.flags.protevil > 0) && (r_ptr->cdefense & CD_EVIL) &&
- ((py.misc.lev + 1) > r_ptr->level))
- {
- if (m_ptr->ml)
- c_recall[m_ptr->mptr].r_cdefense |= CD_EVIL;
- attype = 99;
- adesc = 99;
- }
- p_ptr = &py.misc;
- switch(attype)
- {
- case 1: /*Normal attack */
- if (test_hit(60, (int)r_ptr->level, 0, p_ptr->pac+p_ptr->ptoac,
- CLA_MISC_HIT))
- flag = TRUE;
- break;
- case 2: /*Lose Strength*/
- if (test_hit(-3, (int)r_ptr->level, 0, p_ptr->pac+p_ptr->ptoac,
- CLA_MISC_HIT))
- flag = TRUE;
- break;
- case 3: /*Confusion attack*/
- if (test_hit(10, (int)r_ptr->level, 0, p_ptr->pac+p_ptr->ptoac,
- CLA_MISC_HIT))
- flag = TRUE;
- break;
- case 4: /*Fear attack */
- if (test_hit(10, (int)r_ptr->level, 0, p_ptr->pac+p_ptr->ptoac,
- CLA_MISC_HIT))
- flag = TRUE;
- break;
- case 5: /*Fire attack */
- if (test_hit(10, (int)r_ptr->level, 0, p_ptr->pac+p_ptr->ptoac,
- CLA_MISC_HIT))
- flag = TRUE;
- break;
- case 6: /*Acid attack */
- if (test_hit(0, (int)r_ptr->level, 0, p_ptr->pac+p_ptr->ptoac,
- CLA_MISC_HIT))
- flag = TRUE;
- break;
- case 7: /*Cold attack */
- if (test_hit(10, (int)r_ptr->level, 0, p_ptr->pac+p_ptr->ptoac,
- CLA_MISC_HIT))
- flag = TRUE;
- break;
- case 8: /*Lightning attack*/
- if (test_hit(10, (int)r_ptr->level, 0, p_ptr->pac+p_ptr->ptoac,
- CLA_MISC_HIT))
- flag = TRUE;
- break;
- case 9: /*Corrosion attack*/
- if (test_hit(0, (int)r_ptr->level, 0, p_ptr->pac+p_ptr->ptoac,
- CLA_MISC_HIT))
- flag = TRUE;
- break;
- case 10: /*Blindness attack*/
- if (test_hit(2, (int)r_ptr->level, 0, p_ptr->pac+p_ptr->ptoac,
- CLA_MISC_HIT))
- flag = TRUE;
- break;
- case 11: /*Paralysis attack*/
- if (test_hit(2, (int)r_ptr->level, 0, p_ptr->pac+p_ptr->ptoac,
- CLA_MISC_HIT))
- flag = TRUE;
- break;
- case 12: /*Steal Money */
- if ((test_hit(5, (int)r_ptr->level, 0, (int)py.misc.lev,
- CLA_MISC_HIT))
- && (py.misc.au > 0))
- flag = TRUE;
- break;
- case 13: /*Steal Object */
- if ((test_hit(2, (int)r_ptr->level, 0, (int)py.misc.lev,
- CLA_MISC_HIT))
- && (inven_ctr > 0))
- flag = TRUE;
- break;
- case 14: /*Poison */
- if (test_hit(5, (int)r_ptr->level, 0, p_ptr->pac+p_ptr->ptoac,
- CLA_MISC_HIT))
- flag = TRUE;
- break;
- case 15: /*Lose dexterity*/
- if (test_hit(0, (int)r_ptr->level, 0, p_ptr->pac+p_ptr->ptoac,
- CLA_MISC_HIT))
- flag = TRUE;
- break;
- case 16: /*Lose constitution*/
- if (test_hit(0, (int)r_ptr->level, 0, p_ptr->pac+p_ptr->ptoac,
- CLA_MISC_HIT))
- flag = TRUE;
- break;
- case 17: /*Lose intelligence*/
- if (test_hit(2, (int)r_ptr->level, 0, p_ptr->pac+p_ptr->ptoac,
- CLA_MISC_HIT))
- flag = TRUE;
- break;
- case 18: /*Lose wisdom*/
- if (test_hit(2, (int)r_ptr->level, 0, p_ptr->pac+p_ptr->ptoac,
- CLA_MISC_HIT))
- flag = TRUE;
- break;
- case 19: /*Lose experience*/
- if (test_hit(5, (int)r_ptr->level, 0, p_ptr->pac+p_ptr->ptoac,
- CLA_MISC_HIT))
- flag = TRUE;
- break;
- case 20: /*Aggravate monsters*/
- flag = TRUE;
- break;
- case 21: /*Disenchant */
- if (test_hit(20, (int)r_ptr->level, 0, p_ptr->pac+p_ptr->ptoac,
- CLA_MISC_HIT))
- flag = TRUE;
- break;
- case 22: /*Eat food */
- if (test_hit(5, (int)r_ptr->level, 0, p_ptr->pac+p_ptr->ptoac,
- CLA_MISC_HIT))
- flag = TRUE;
- break;
- case 23: /*Eat light */
- if (test_hit(5, (int)r_ptr->level, 0, p_ptr->pac+p_ptr->ptoac,
- CLA_MISC_HIT))
- flag = TRUE;
- break;
- case 24: /*Eat charges */
- if ((test_hit(15, (int)r_ptr->level, 0, p_ptr->pac+p_ptr->ptoac,
- CLA_MISC_HIT)) &&
- (inven_ctr > 0)) /* check to make sure an object exists */
- flag = TRUE;
- break;
- case 99:
- flag = TRUE;
- break;
- default:
- break;
- }
- if (flag)
- {
- /* can not strcat to cdesc because the creature may have
- multiple attacks */
- disturb (1, 0);
- (void) strcpy(tmp_str, cdesc);
- switch(adesc)
- {
- case 1: msg_print(strcat(tmp_str, "hits you.")); break;
- case 2: msg_print(strcat(tmp_str, "bites you.")); break;
- case 3: msg_print(strcat(tmp_str, "claws you.")); break;
- case 4: msg_print(strcat(tmp_str, "stings you.")); break;
- case 5: msg_print(strcat(tmp_str, "touches you.")); break;
- #if 0
- case 6: msg_print(strcat(tmp_str, "kicks you.")); break;
- #endif
- case 7: msg_print(strcat(tmp_str, "gazes at you.")); break;
- case 8: msg_print(strcat(tmp_str, "breathes on you.")); break;
- case 9: msg_print(strcat(tmp_str, "spits on you.")); break;
- case 10: msg_print(strcat(tmp_str,"makes a horrible wail."));break;
- #if 0
- case 11: msg_print(strcat(tmp_str, "embraces you.")); break;
- #endif
- case 12: msg_print(strcat(tmp_str, "crawls on you.")); break;
- case 13:
- msg_print(strcat(tmp_str, "releases a cloud of spores.")); break;
- case 14: msg_print(strcat(tmp_str, "begs you for money.")); break;
- case 15: msg_print("You've been slimed!"); break;
- case 16: msg_print(strcat(tmp_str, "crushes you.")); break;
- case 17: msg_print(strcat(tmp_str, "tramples you.")); break;
- case 18: msg_print(strcat(tmp_str, "drools on you.")); break;
- case 19:
- switch(randint(9))
- {
- case 1: msg_print(strcat(tmp_str, "insults you!")); break;
- case 2:
- msg_print(strcat(tmp_str, "insults your mother!")); break;
- case 3:
- msg_print(strcat(tmp_str, "gives you the finger!")); break;
- case 4: msg_print(strcat(tmp_str, "humiliates you!")); break;
- case 5: msg_print(strcat(tmp_str, "wets on your leg!")); break;
- case 6: msg_print(strcat(tmp_str, "defiles you!")); break;
- case 7: msg_print(strcat(tmp_str, "dances around you!"));break;
- case 8:
- msg_print(strcat(tmp_str, "makes obscene gestures!")); break;
- case 9: msg_print(strcat(tmp_str, "moons you!!!")); break;
- }
- break;
- case 99: msg_print(strcat(tmp_str, "is repelled.")); break;
- default: break;
- }
-
- notice = TRUE;
- /* always fail to notice attack if creature invisible, set notice
- and visible here since creature may be visible when attacking
- and then teleport afterwards (becoming effectively invisible) */
- if (!m_ptr->ml)
- {
- visible = FALSE;
- notice = FALSE;
- }
- else
- visible = TRUE;
-
- damage = damroll (adice, asides);
- switch(attype)
- {
- case 1: /*Normal attack */
- /* round half-way case down */
- damage -= ((p_ptr->pac+p_ptr->ptoac) * damage) / 200;
- take_hit(damage, ddesc);
- break;
- case 2: /*Lose Strength*/
- take_hit(damage, ddesc);
- if (py.flags.sustain_str)
- msg_print("You feel weaker for a moment, but it passes.");
- else if (randint(2) == 1)
- {
- msg_print("You feel weaker.");
- (void) dec_stat (A_STR);
- }
- else
- notice = FALSE;
- break;
- case 3: /*Confusion attack*/
- f_ptr = &py.flags;
- take_hit(damage, ddesc);
- if (randint(2) == 1)
- {
- if (f_ptr->confused < 1)
- {
- msg_print("You feel confused.");
- f_ptr->confused += randint((int)r_ptr->level);
- }
- else
- notice = FALSE;
- f_ptr->confused += 3;
- }
- else
- notice = FALSE;
- break;
- case 4: /*Fear attack */
- f_ptr = &py.flags;
- take_hit(damage, ddesc);
- if (player_saves())
- msg_print("You resist the effects!");
- else if (f_ptr->afraid < 1)
- {
- msg_print("You are suddenly afraid!");
- f_ptr->afraid += 3 + randint((int)r_ptr->level);
- }
- else
- {
- f_ptr->afraid += 3;
- notice = FALSE;
- }
- break;
- case 5: /*Fire attack */
- msg_print("You are enveloped in flames!");
- fire_dam(damage, ddesc);
- break;
- case 6: /*Acid attack */
- msg_print("You are covered in acid!");
- acid_dam(damage, ddesc);
- break;
- case 7: /*Cold attack */
- msg_print("You are covered with frost!");
- cold_dam(damage, ddesc);
- break;
- case 8: /*Lightning attack*/
- msg_print("Lightning strikes you!");
- light_dam(damage, ddesc);
- break;
- case 9: /*Corrosion attack*/
- msg_print("A stinging red gas swirls about you.");
- corrode_gas(ddesc);
- take_hit(damage, ddesc);
- break;
- case 10: /*Blindness attack*/
- f_ptr = &py.flags;
- take_hit(damage, ddesc);
- if (f_ptr->blind < 1)
- {
- f_ptr->blind += 10 + randint((int)r_ptr->level);
- msg_print("Your eyes begin to sting.");
- }
- else
- {
- f_ptr->blind += 5;
- notice = FALSE;
- }
- break;
- case 11: /*Paralysis attack*/
- f_ptr = &py.flags;
- take_hit(damage, ddesc);
- if (player_saves())
- msg_print("You resist the effects!");
- else if (f_ptr->paralysis < 1)
- {
- if (f_ptr->free_act)
- msg_print("You are unaffected.");
- else
- {
- f_ptr->paralysis = randint((int)r_ptr->level) + 3;
- msg_print("You are paralyzed.");
- }
- }
- else
- notice = FALSE;
- break;
- case 12: /*Steal Money */
- if ((py.flags.paralysis < 1) &&
- (randint(124) < py.stats.use_stat[A_DEX]))
- msg_print("You quickly protect your money pouch!");
- else
- {
- gold = (p_ptr->au/10) + randint(25);
- if (gold > p_ptr->au)
- p_ptr->au = 0;
- else
- p_ptr->au -= gold;
- msg_print("Your purse feels lighter.");
- prt_gold();
- }
- if (randint(2) == 1)
- {
- msg_print("There is a puff of smoke!");
- teleport_away(monptr, MAX_SIGHT);
- }
- break;
- case 13: /*Steal Object */
- if ((py.flags.paralysis < 1) &&
- (randint(124) < py.stats.use_stat[A_DEX]))
- msg_print("You grab hold of your backpack!");
- else
- {
- i = randint(inven_ctr) - 1;
- inven_destroy(i);
- msg_print("Your backpack feels lighter.");
- }
- if (randint(2) == 1)
- {
- msg_print("There is a puff of smoke!");
- teleport_away(monptr, MAX_SIGHT);
- }
- break;
- case 14: /*Poison */
- f_ptr = &py.flags;
- take_hit(damage, ddesc);
- msg_print("You feel very sick.");
- f_ptr->poisoned += randint((int)r_ptr->level)+5;
- break;
- case 15: /*Lose dexterity */
- f_ptr = &py.flags;
- take_hit(damage, ddesc);
- if (f_ptr->sustain_dex)
- msg_print("You feel clumsy for a moment, but it passes.");
- else
- {
- msg_print("You feel more clumsy.");
- (void) dec_stat (A_DEX);
- }
- break;
- case 16: /*Lose constitution */
- f_ptr = &py.flags;
- take_hit(damage, ddesc);
- if (f_ptr->sustain_con)
- msg_print("Your body resists the effects of the disease.");
- else
- {
- msg_print("Your health is damaged!");
- (void) dec_stat (A_CON);
- }
- break;
- case 17: /*Lose intelligence */
- f_ptr = &py.flags;
- take_hit(damage, ddesc);
- msg_print("You have trouble thinking clearly.");
- if (f_ptr->sustain_int)
- msg_print("But your mind quickly clears.");
- else
- (void) dec_stat (A_INT);
- break;
- case 18: /*Lose wisdom */
- f_ptr = &py.flags;
- take_hit(damage, ddesc);
- if (f_ptr->sustain_wis)
- msg_print("Your wisdom is sustained.");
- else
- {
- msg_print("Your wisdom is drained.");
- (void) dec_stat (A_WIS);
- }
- break;
- case 19: /*Lose experience */
- msg_print("You feel your life draining away!");
- lose_exp(damage + (py.misc.exp / 100)*MON_DRAIN_LIFE);
- break;
- case 20: /*Aggravate monster*/
- (void) aggravate_monster(20);
- break;
- case 21: /*Disenchant */
- flag = FALSE;
- switch(randint(7))
- {
- case 1: i = INVEN_WIELD; break;
- case 2: i = INVEN_BODY; break;
- case 3: i = INVEN_ARM; break;
- case 4: i = INVEN_OUTER; break;
- case 5: i = INVEN_HANDS; break;
- case 6: i = INVEN_HEAD; break;
- case 7: i = INVEN_FEET; break;
- }
- i_ptr = &inventory[i];
- if (i_ptr->tohit > 0)
- {
- i_ptr->tohit -= randint(2);
- /* don't send it below zero */
- if (i_ptr->tohit < 0)
- i_ptr->tohit = 0;
- flag = TRUE;
- }
- if (i_ptr->todam > 0)
- {
- i_ptr->todam -= randint(2);
- /* don't send it below zero */
- if (i_ptr->todam < 0)
- i_ptr->todam = 0;
- flag = TRUE;
- }
- if (i_ptr->toac > 0)
- {
- i_ptr->toac -= randint(2);
- /* don't send it below zero */
- if (i_ptr->toac < 0)
- i_ptr->toac = 0;
- flag = TRUE;
- }
- if (flag)
- {
- msg_print("There is a static feeling in the air.");
- calc_bonuses ();
- }
- else
- notice = FALSE;
- break;
- case 22: /*Eat food */
- if (find_range(TV_FOOD, TV_NEVER, &i, &j))
- {
- inven_destroy(i);
- msg_print ("It got at your rations!");
- }
- else
- notice = FALSE;
- break;
- case 23: /*Eat light */
- i_ptr = &inventory[INVEN_LIGHT];
- if (i_ptr->p1 > 0)
- {
- i_ptr->p1 -= (250 + randint(250));
- if (i_ptr->p1 < 1) i_ptr->p1 = 1;
- if (py.flags.blind < 1)
- msg_print("Your light dims.");
- else
- notice = FALSE;
- }
- else
- notice = FALSE;
- break;
- case 24: /*Eat charges */
- i = randint(inven_ctr) - 1;
- j = r_ptr->level;
- i_ptr = &inventory[i];
- if (((i_ptr->tval == TV_STAFF) || (i_ptr->tval == TV_WAND))
- && (i_ptr->p1 > 0))
- {
- m_ptr->hp += j*i_ptr->p1;
- i_ptr->p1 = 0;
- if (! known2_p (i_ptr))
- add_inscribe (i_ptr, ID_EMPTY);
- msg_print("Energy drains from your pack!");
- }
- else
- notice = FALSE;
- break;
- case 99:
- notice = FALSE;
- break;
- default:
- notice = FALSE;
- break;
- }
-
- /* Moved here from mon_move, so that monster only confused if it
- actually hits. A monster that has been repelled has not hit
- the player, so it should not be confused. */
- if (py.flags.confuse_monster && adesc != 99)
- {
- msg_print("Your hands stop glowing.");
- py.flags.confuse_monster = FALSE;
- if ((randint(MAX_MONS_LEVEL) < r_ptr->level) ||
- (CD_NO_SLEEP & r_ptr->cdefense))
- (void) sprintf(tmp_str, "%sis unaffected.", cdesc);
- else
- {
- (void) sprintf(tmp_str, "%sappears confused.", cdesc);
- m_ptr->confused = TRUE;
- }
- msg_print(tmp_str);
- if (visible && !death && randint(4) == 1)
- c_recall[m_ptr->mptr].r_cdefense |= r_ptr->cdefense &
- CD_NO_SLEEP;
- }
-
- /* increase number of attacks if notice true, or if visible and had
- previously noticed the attack (in which case all this does is
- help player learn damage), note that in the second case do
- not increase attacks if creature repelled (no damage done) */
- if ((notice ||
- (visible && c_recall[m_ptr->mptr].r_attacks[attackn] != 0 &&
- attype != 99))
- && c_recall[m_ptr->mptr].r_attacks[attackn] < MAX_UCHAR)
- c_recall[m_ptr->mptr].r_attacks[attackn]++;
- if (death && c_recall[m_ptr->mptr].r_deaths < MAX_SHORT)
- c_recall[m_ptr->mptr].r_deaths++;
- }
- else
- {
- if ((adesc >= 1 && adesc <= 3) || (adesc == 6))
- {
- disturb (1, 0);
- (void) strcpy(tmp_str, cdesc);
- msg_print(strcat(tmp_str, "misses you."));
- }
- }
- if (attackn < MAX_MON_NATTACK-1)
- attackn++;
- else
- break;
- }
- }
-
-
- /* Make the move if possible, five choices -RAK- */
- static void make_move(monptr, mm, rcmove)
- int monptr;
- int *mm;
- int32u *rcmove;
- {
- int i, newy, newx, do_turn, do_move, stuck_door;
- int32u movebits;
- register cave_type *c_ptr;
- register monster_type *m_ptr;
- register inven_type *t_ptr;
- #ifdef ATARIST_MWC
- int32u holder;
- #endif
-
- i = 0;
- do_turn = FALSE;
- do_move = FALSE;
- m_ptr = &m_list[monptr];
- movebits = c_list[m_ptr->mptr].cmove;
- do
- {
- /* Get new position */
- newy = m_ptr->fy;
- newx = m_ptr->fx;
- (void) mmove(mm[i], &newy, &newx);
- c_ptr = &cave[newy][newx];
- if (c_ptr->fval != BOUNDARY_WALL)
- {
- /* Floor is open? */
- if (c_ptr->fval <= MAX_OPEN_SPACE)
- do_move = TRUE;
- /* Creature moves through walls? */
- #ifdef ATARIST_MWC
- else if (movebits & (holder = CM_PHASE))
- #else
- else if (movebits & CM_PHASE)
- #endif
- {
- do_move = TRUE;
- #ifdef ATARIST_MWC
- *rcmove |= holder;
- #else
- *rcmove |= CM_PHASE;
- #endif
- }
- /* Creature can open doors? */
- else if (c_ptr->tptr != 0)
- {
- t_ptr = &t_list[c_ptr->tptr];
- #ifdef ATARIST_MWC
- if (movebits & (holder = CM_OPEN_DOOR))
- #else
- if (movebits & CM_OPEN_DOOR)
- #endif
- { /* Creature can open doors. */
- stuck_door = FALSE;
- if (t_ptr->tval == TV_CLOSED_DOOR)
- {
- do_turn = TRUE;
- if (t_ptr->p1 == 0) /* Closed doors */
- do_move = TRUE;
- else if (t_ptr->p1 > 0) /* Locked doors */
- {
- if (randint((m_ptr->hp+1)*(50+t_ptr->p1)) <
- 40*(m_ptr->hp-10-t_ptr->p1))
- t_ptr->p1 = 0;
- }
- else if (t_ptr->p1 < 0) /* Stuck doors */
- {
- if (randint((m_ptr->hp+1)*(50-t_ptr->p1)) <
- 40*(m_ptr->hp-10+t_ptr->p1))
- {
- msg_print("You hear a door burst open!");
- disturb (1, 0);
- stuck_door = TRUE;
- do_move = TRUE;
- }
- }
- }
- else if (t_ptr->tval == TV_SECRET_DOOR)
- {
- do_turn = TRUE;
- do_move = TRUE;
- }
- if (do_move)
- {
- invcopy(t_ptr, OBJ_OPEN_DOOR);
- if (stuck_door) /* 50% chance of breaking door */
- t_ptr->p1 = 1 - randint(2);
- c_ptr->fval = CORR_FLOOR;
- lite_spot(newy, newx);
- #ifdef ATARIST_MWC
- *rcmove |= holder;
- #else
- *rcmove |= CM_OPEN_DOOR;
- #endif
- do_move = FALSE;
- }
- }
- else
- { /* Creature can not open doors, must bash them */
- if (t_ptr->tval == TV_CLOSED_DOOR)
- {
- do_turn = TRUE;
- if (randint((m_ptr->hp+1)*(80+abs(t_ptr->p1))) <
- 40*(m_ptr->hp-20-abs(t_ptr->p1)))
- {
- invcopy(t_ptr, OBJ_OPEN_DOOR);
- /* 50% chance of breaking door */
- t_ptr->p1 = 1 - randint(2);
- c_ptr->fval = CORR_FLOOR;
- lite_spot(newy, newx);
- msg_print ("You hear a door burst open!");
- disturb (1, 0);
- }
- }
- }
- }
- /* Glyph of warding present? */
- if (do_move && (c_ptr->tptr != 0) &&
- (t_list[c_ptr->tptr].tval == TV_VIS_TRAP) &&
- (t_list[c_ptr->tptr].subval == 99))
- {
- if (randint(OBJ_RUNE_PROT) < c_list[m_ptr->mptr].level)
- {
- if ((newy==char_row) && (newx==char_col))
- msg_print("The rune of protection is broken!");
- (void) delete_object(newy, newx);
- }
- else
- {
- do_move = FALSE;
- /* If the creature moves only to attack, */
- /* don't let it move if the glyph prevents */
- /* it from attacking */
- if (movebits & CM_ATTACK_ONLY)
- do_turn = TRUE;
- }
- }
- /* Creature has attempted to move on player? */
- if (do_move)
- if (c_ptr->cptr == 1)
- {
- /* if the monster is not lit, must call update_mon, it may
- be faster than character, and hence could have just
- moved next to character this same turn */
- if (!m_ptr->ml)
- update_mon(monptr);
- make_attack(monptr);
- do_move = FALSE;
- do_turn = TRUE;
- }
- /* Creature is attempting to move on other creature? */
- else if ((c_ptr->cptr > 1) &&
- ((newy != m_ptr->fy) ||
- (newx != m_ptr->fx)))
- {
- /* Creature eats other creatures? */
- #ifdef ATARIST_MWC
- if ((movebits & (holder = CM_EATS_OTHER)) &&
- #else
- if ((movebits & CM_EATS_OTHER) &&
- #endif
- (c_list[m_ptr->mptr].mexp >=
- c_list[m_list[c_ptr->cptr].mptr].mexp))
- {
- if (m_list[c_ptr->cptr].ml)
- #ifdef ATARIST_MWC
- *rcmove |= holder;
- #else
- *rcmove |= CM_EATS_OTHER;
- #endif
- /* It ate an already processed monster. Handle normally. */
- if (monptr < c_ptr->cptr)
- delete_monster((int) c_ptr->cptr);
- /* If it eats this monster, an already processed monster
- will take its place, causing all kinds of havoc. Delay
- the kill a bit. */
- else
- fix1_delete_monster((int) c_ptr->cptr);
- }
- else
- do_move = FALSE;
- }
- /* Creature has been allowed move. */
- if (do_move)
- {
- /* Pick up or eat an object */
- #ifdef ATARIST_MWC
- if (movebits & (holder = CM_PICKS_UP))
- #else
- if (movebits & CM_PICKS_UP)
- #endif
- {
- c_ptr = &cave[newy][newx];
-
- if ((c_ptr->tptr != 0)
- && (t_list[c_ptr->tptr].tval <= TV_MAX_OBJECT))
- {
- #ifdef ATARIST_MWC
- *rcmove |= holder;
- #else
- *rcmove |= CM_PICKS_UP;
- #endif
- (void) delete_object(newy, newx);
- }
- }
- /* Move creature record */
- move_rec((int)m_ptr->fy, (int)m_ptr->fx, newy, newx);
- if (m_ptr->ml)
- {
- m_ptr->ml = FALSE;
- lite_spot ((int)m_ptr->fy, (int)m_ptr->fx);
- }
- m_ptr->fy = newy;
- m_ptr->fx = newx;
- m_ptr->cdis = distance (char_row, char_col, newy, newx);
- do_turn = TRUE;
- }
- }
- i++;
- /* Up to 5 attempts at moving, give up. */
- }
- while ((!do_turn) && (i < 5));
- }
-
-
- /* Creatures can cast spells too. (Dragon Breath) -RAK- */
- /* cast_spell = true if creature changes position */
- /* took_turn = true if creature casts a spell */
- static void mon_cast_spell(monptr, took_turn)
- int monptr;
- int *took_turn;
- {
- int32u i;
- int y, x, chance, thrown_spell, r1;
- register int k;
- int spell_choice[30];
- vtype cdesc, outval, ddesc;
- register monster_type *m_ptr;
- register creature_type *r_ptr;
- #ifdef ATARIST_MWC
- int32u holder;
- #endif
-
- if (death)
- return;
-
- m_ptr = &m_list[monptr];
- r_ptr = &c_list[m_ptr->mptr];
- chance = (int)(r_ptr->spells & CS_FREQ);
- /* 1 in x chance of casting spell */
- if (randint(chance) != 1)
- *took_turn = FALSE;
- /* Must be within certain range */
- else if (m_ptr->cdis > MAX_SPELL_DIS)
- *took_turn = FALSE;
- /* Must have unobstructed Line-Of-Sight */
- else if (!los(char_row, char_col, (int)m_ptr->fy, (int)m_ptr->fx))
- *took_turn = FALSE;
- else /* Creature is going to cast a spell */
- {
- *took_turn = TRUE;
- /* Check to see if monster should be lit. */
- update_mon (monptr);
- /* Describe the attack */
- if (m_ptr->ml)
- (void) sprintf(cdesc, "The %s ", r_ptr->name);
- else
- (void) strcpy(cdesc, "It ");
- /* For "DIED_FROM" string */
- #ifdef ATARIST_MWC
- holder = CM_WIN;
- if (holder & r_ptr->cmove)
- #else
- if (CM_WIN & r_ptr->cmove)
- #endif
- (void) sprintf(ddesc, "The %s", r_ptr->name);
- else if (is_a_vowel (r_ptr->name[0]))
- (void) sprintf (ddesc, "an %s", r_ptr->name);
- else
- (void) sprintf(ddesc, "a %s", r_ptr->name);
- /* End DIED_FROM */
-
- /* Extract all possible spells into spell_choice */
- #ifdef ATARIST_MWC
- holder = ~CS_FREQ;
- i = (r_ptr->spells & holder);
- #else
- i = (r_ptr->spells & ~CS_FREQ);
- #endif
- k = 0;
- while (i != 0)
- {
- spell_choice[k] = bit_pos(&i);
- k++;
- }
- /* Choose a spell to cast */
- thrown_spell = spell_choice[randint(k) - 1];
- thrown_spell++;
- /* all except teleport_away() and drain mana spells always disturb */
- if (thrown_spell > 6 && thrown_spell != 17)
- disturb (1, 0);
- /* save some code/data space here, with a small time penalty */
- if ((thrown_spell < 14 && thrown_spell > 6) || (thrown_spell == 16))
- {
- (void) strcat(cdesc, "casts a spell.");
- msg_print(cdesc);
- }
- /* Cast the spell. */
- switch(thrown_spell)
- {
- case 5: /*Teleport Short*/
- teleport_away(monptr, 5);
- break;
- case 6: /*Teleport Long */
- teleport_away(monptr, MAX_SIGHT);
- break;
- case 7: /*Teleport To */
- teleport_to((int)m_ptr->fy, (int)m_ptr->fx);
- break;
- case 8: /*Light Wound */
- if (player_saves())
- msg_print("You resist the effects of the spell.");
- else
- take_hit(damroll(3, 8), ddesc);
- break;
- case 9: /*Serious Wound */
- if (player_saves())
- msg_print("You resist the effects of the spell.");
- else
- take_hit(damroll(8, 8), ddesc);
- break;
- case 10: /*Hold Person */
- if (py.flags.free_act)
- msg_print("You are unaffected.");
- else if (player_saves())
- msg_print("You resist the effects of the spell.");
- else if (py.flags.paralysis > 0)
- py.flags.paralysis += 2;
- else
- py.flags.paralysis = randint(5)+4;
- break;
- case 11: /*Cause Blindness*/
- if (player_saves())
- msg_print("You resist the effects of the spell.");
- else if (py.flags.blind > 0)
- py.flags.blind += 6;
- else
- py.flags.blind += 12 + randint(3);
- break;
- case 12: /*Cause Confuse */
- if (player_saves())
- msg_print("You resist the effects of the spell.");
- else if (py.flags.confused > 0)
- py.flags.confused += 2;
- else
- py.flags.confused = randint(5) + 3;
- break;
- case 13: /*Cause Fear */
- if (player_saves())
- msg_print("You resist the effects of the spell.");
- else if (py.flags.afraid > 0)
- py.flags.afraid += 2;
- else
- py.flags.afraid = randint(5) + 3;
- break;
- case 14: /*Summon Monster*/
- (void) strcat(cdesc, "magically summons a monster!");
- msg_print(cdesc);
- y = char_row;
- x = char_col;
- /* in case compact_monster() is called,it needs monptr */
- hack_monptr = monptr;
- (void) summon_monster(&y, &x, FALSE);
- hack_monptr = -1;
- update_mon ((int)cave[y][x].cptr);
- break;
- case 15: /*Summon Undead*/
- (void) strcat(cdesc, "magically summons an undead!");
- msg_print(cdesc);
- y = char_row;
- x = char_col;
- /* in case compact_monster() is called,it needs monptr */
- hack_monptr = monptr;
- (void) summon_undead(&y, &x);
- hack_monptr = -1;
- update_mon ((int)cave[y][x].cptr);
- break;
- case 16: /*Slow Person */
- if (py.flags.free_act)
- msg_print("You are unaffected.");
- else if (player_saves())
- msg_print("You resist the effects of the spell.");
- else if (py.flags.slow > 0)
- py.flags.slow += 2;
- else
- py.flags.slow = randint(5) + 3;
- break;
- case 17: /*Drain Mana */
- if (py.misc.cmana > 0)
- {
- disturb (1, 0);
- (void) sprintf(outval, "%sdraws psychic energy from you!",cdesc);
- msg_print(outval);
- if (m_ptr->ml)
- {
- (void) sprintf(outval, "%sappears healthier.", cdesc);
- msg_print(outval);
- }
- r1 = (randint((int)r_ptr->level) >> 1) + 1;
- if (r1 > py.misc.cmana)
- {
- r1 = py.misc.cmana;
- py.misc.cmana = 0;
- py.misc.cmana_frac = 0;
- }
- else
- py.misc.cmana -= r1;
- prt_cmana();
- m_ptr->hp += 6*(r1);
- }
- break;
- case 20: /*Breath Light */
- (void) strcat(cdesc, "breathes lightning.");
- msg_print(cdesc);
- breath(GF_LIGHTNING, char_row, char_col, (m_ptr->hp / 4), ddesc,
- monptr);
- break;
- case 21: /*Breath Gas */
- (void) strcat(cdesc, "breathes gas.");
- msg_print(cdesc);
- breath(GF_POISON_GAS, char_row, char_col, (m_ptr->hp / 3), ddesc,
- monptr);
- break;
- case 22: /*Breath Acid */
- (void) strcat(cdesc, "breathes acid.");
- msg_print(cdesc);
- breath(GF_ACID, char_row, char_col, (m_ptr->hp / 3), ddesc, monptr);
- break;
- case 23: /*Breath Frost */
- (void) strcat(cdesc, "breathes frost.");
- msg_print(cdesc);
- breath(GF_FROST, char_row, char_col, (m_ptr->hp / 3), ddesc, monptr);
- break;
- case 24: /*Breath Fire */
- (void) strcat(cdesc, "breathes fire.");
- msg_print(cdesc);
- breath(GF_FIRE, char_row, char_col, (m_ptr->hp / 3), ddesc, monptr);
- break;
- default:
- (void) strcat (cdesc, "cast unknown spell.");
- msg_print(cdesc);
- }
- /* End of spells */
- if (m_ptr->ml)
- {
- c_recall[m_ptr->mptr].r_spells |= 1L << (thrown_spell-1);
- if ((c_recall[m_ptr->mptr].r_spells & CS_FREQ) != CS_FREQ)
- c_recall[m_ptr->mptr].r_spells++;
- if (death && c_recall[m_ptr->mptr].r_deaths < MAX_SHORT)
- c_recall[m_ptr->mptr].r_deaths++;
- }
- }
- }
-
-
- /* Places creature adjacent to given location -RAK- */
- /* Rats and Flys are fun! */
- int multiply_monster(y, x, cr_index, monptr)
- int y, x, cr_index;
- int monptr;
- {
- register int i, j, k;
- register cave_type *c_ptr;
- int result;
- #ifdef ATARIST_MWC
- int32u holder;
- #endif
-
- i = 0;
- do
- {
- j = y - 2 + randint(3);
- k = x - 2 + randint(3);
- /* don't create a new creature on top of the old one, that causes
- invincible/invisible creatures to appear */
- if (in_bounds(j, k) && (j != y || k != x))
- {
- c_ptr = &cave[j][k];
- if ((c_ptr->fval <= MAX_OPEN_SPACE) && (c_ptr->tptr == 0) &&
- (c_ptr->cptr != 1))
- {
- if (c_ptr->cptr > 1) /* Creature there already? */
- {
- /* Some critters are cannibalistic! */
- #ifdef ATARIST_MWC
- holder = CM_EATS_OTHER;
- if ((c_list[cr_index].cmove & holder)
- #else
- if ((c_list[cr_index].cmove & CM_EATS_OTHER)
- #endif
- /* Check the experience level -CJS- */
- && c_list[cr_index].mexp >=
- c_list[m_list[c_ptr->cptr].mptr].mexp)
- {
- /* It ate an already processed monster.Handle normally.*/
- if (monptr < c_ptr->cptr)
- delete_monster((int) c_ptr->cptr);
- /* If it eats this monster, an already processed mosnter
- will take its place, causing all kinds of havoc.
- Delay the kill a bit. */
- else
- fix1_delete_monster((int) c_ptr->cptr);
-
- /* in case compact_monster() is called,it needs monptr */
- hack_monptr = monptr;
- /* Place_monster() may fail if monster list full. */
- result = place_monster(j, k, cr_index, FALSE);
- hack_monptr = -1;
- if (! result)
- return FALSE;
- mon_tot_mult++;
- return check_mon_lite(j, k);
- }
- }
- else
- /* All clear, place a monster */
- {
- /* in case compact_monster() is called,it needs monptr */
- hack_monptr = monptr;
- /* Place_monster() may fail if monster list full. */
- result = place_monster(j, k, cr_index, FALSE);
- hack_monptr = -1;
- if (! result)
- return FALSE;
- mon_tot_mult++;
- return check_mon_lite(j, k);
- }
- }
- }
- i++;
- }
- while (i <= 18);
- return FALSE;
- }
-
-
- /* Move the critters about the dungeon -RAK- */
- static void mon_move(monptr, rcmove)
- int monptr;
- int32u *rcmove;
- {
- register int i, j;
- int k, move_test, dir;
- #ifdef M_XENIX
- /* Avoid 'register' bug. */
- creature_type *r_ptr;
- #else
- register creature_type *r_ptr;
- #endif
- register monster_type *m_ptr;
- int mm[9];
- #ifdef ATARIST_MWC
- int32u holder;
- #endif
- int rest_val;
-
- m_ptr = &m_list[monptr];
- r_ptr = &c_list[m_ptr->mptr];
- /* Does the critter multiply? */
- /* rest could be negative, to be safe, only use mod with positive values. */
- rest_val = abs (py.flags.rest);
- #ifdef ATARIST_MWC
- holder = CM_MULTIPLY;
- if ((r_ptr->cmove & holder) && (MAX_MON_MULT >= mon_tot_mult) &&
- #else
- if ((r_ptr->cmove & CM_MULTIPLY) && (MAX_MON_MULT >= mon_tot_mult) &&
- #endif
- ((rest_val % MON_MULT_ADJ) == 0))
- {
- k = 0;
- for (i = m_ptr->fy-1; i <= m_ptr->fy+1; i++)
- for (j = m_ptr->fx-1; j <= m_ptr->fx+1; j++)
- if (in_bounds(i, j) && (cave[i][j].cptr > 1))
- k++;
- /* can't call randint with a value of zero, increment counter
- to allow creature multiplication */
- if (k == 0)
- k++;
- if ((k < 4) && (randint(k*MON_MULT_ADJ) == 1))
- if (multiply_monster((int)m_ptr->fy, (int)m_ptr->fx,
- (int)m_ptr->mptr, monptr))
- #ifdef ATARIST_MWC
- *rcmove |= holder;
- #else
- *rcmove |= CM_MULTIPLY;
- #endif
- }
- move_test = FALSE;
-
- /* if in wall, must immediately escape to a clear area */
- #ifdef ATARIST_MWC
- holder = CM_PHASE;
- if (!(r_ptr->cmove & holder) &&
- #else
- if (!(r_ptr->cmove & CM_PHASE) &&
- #endif
- (cave[m_ptr->fy][m_ptr->fx].fval >= MIN_CAVE_WALL))
- {
- /* If the monster is already dead, don't kill it again!
- This can happen for monsters moving faster than the player. They
- will get multiple moves, but should not if they die on the first
- move. This is only a problem for monsters stuck in rock. */
- if (m_ptr->hp < 0)
- return;
-
- k = 0;
- dir = 1;
- /* note direction of for loops matches direction of keypad from 1 to 9*/
- /* do not allow attack against the player */
- /* Must cast fy-1 to signed int, so that a nagative value of i will
- fail the comparison. */
- for (i = m_ptr->fy+1; i >= (int)(m_ptr->fy-1); i--)
- for (j = m_ptr->fx-1; j <= m_ptr->fx+1; j++)
- {
- if ((dir != 5) && (cave[i][j].fval <= MAX_OPEN_SPACE)
- && (cave[i][j].cptr != 1))
- mm[k++] = dir;
- dir++;
- }
- if (k != 0)
- {
- /* put a random direction first */
- dir = randint (k) - 1;
- i = mm[0];
- mm[0] = mm[dir];
- mm[dir] = i;
- make_move (monptr, mm, rcmove);
- /* this can only fail if mm[0] has a rune of protection */
- }
- /* if still in a wall, let it dig itself out, but also apply some
- more damage */
- if (cave[m_ptr->fy][m_ptr->fx].fval >= MIN_CAVE_WALL)
- {
- /* in case the monster dies, may need to call fix1_delete_monster()
- instead of delete_monsters() */
- hack_monptr = monptr;
- i = mon_take_hit(monptr, damroll (8, 8));
- hack_monptr = -1;
- if (i >= 0)
- {
- msg_print("You hear a scream muffled by rock!");
- prt_experience();
- }
- else
- {
- msg_print ("A creature digs itself out from the rock!");
- (void) twall ((int)m_ptr->fy, (int)m_ptr->fx, 1, 0);
- }
- }
- return; /* monster movement finished */
- }
- /* Creature is confused? Chance it becomes un-confused */
- else if (m_ptr->confused)
- {
- mm[0] = randint(9);
- mm[1] = randint(9);
- mm[2] = randint(9);
- mm[3] = randint(9);
- mm[4] = randint(9);
- /* don't move him if he is not supposed to move! */
- if (!(r_ptr->cmove & CM_ATTACK_ONLY))
- make_move(monptr, mm, rcmove);
- if (randint(8) == 1)
- m_ptr->confused = FALSE;
- move_test = TRUE;
- }
- /* Creature may cast a spell */
- else if (r_ptr->spells != 0)
- mon_cast_spell(monptr, &move_test);
- if (!move_test)
- {
- /* 75% random movement */
- if ((r_ptr->cmove & CM_75_RANDOM) && (randint(100) < 75))
- {
- mm[0] = randint(9);
- mm[1] = randint(9);
- mm[2] = randint(9);
- mm[3] = randint(9);
- mm[4] = randint(9);
- *rcmove |= CM_75_RANDOM;
- make_move(monptr, mm, rcmove);
- }
- /* 40% random movement */
- else if ((r_ptr->cmove & CM_40_RANDOM) && (randint(100) < 40))
- {
- mm[0] = randint(9);
- mm[1] = randint(9);
- mm[2] = randint(9);
- mm[3] = randint(9);
- mm[4] = randint(9);
- *rcmove |= CM_40_RANDOM;
- make_move(monptr, mm, rcmove);
- }
- /* 20% random movement */
- else if ((r_ptr->cmove & CM_20_RANDOM) && (randint(100) < 20))
- {
- mm[0] = randint(9);
- mm[1] = randint(9);
- mm[2] = randint(9);
- mm[3] = randint(9);
- mm[4] = randint(9);
- *rcmove |= CM_20_RANDOM;
- make_move(monptr, mm, rcmove);
- }
- /* Normal movement */
- else if (r_ptr->cmove & CM_MOVE_NORMAL)
- {
- if (randint(200) == 1)
- {
- mm[0] = randint(9);
- mm[1] = randint(9);
- mm[2] = randint(9);
- mm[3] = randint(9);
- mm[4] = randint(9);
- }
- else
- get_moves(monptr, mm);
- *rcmove |= CM_MOVE_NORMAL;
- make_move(monptr, mm, rcmove);
- }
- /* Attack, but don't move */
- else if (r_ptr->cmove & CM_ATTACK_ONLY)
- {
- if (m_ptr->cdis < 2)
- {
- get_moves(monptr, mm);
- make_move(monptr, mm, rcmove);
- }
- else
- /* Learn that the monster does does not move when it should have
- moved, but didn't. */
- *rcmove |= CM_ATTACK_ONLY;
- }
- else if ((r_ptr->cmove & CM_ONLY_MAGIC) && (m_ptr->cdis < 2))
- {
- /* A little hack for Quylthulgs, so that one will eventually notice
- that they have no physical attacks. */
- if (c_recall[m_ptr->mptr].r_attacks[0] < MAX_UCHAR)
- c_recall[m_ptr->mptr].r_attacks[0]++;
- /* Another little hack for Quylthulgs, so that one can eventually
- learn their speed. */
- if (c_recall[m_ptr->mptr].r_attacks[0] > 20)
- c_recall[m_ptr->mptr].r_cmove |= CM_ONLY_MAGIC;
- }
- }
- }
-
-
- /* Creatures movement and attacking are done from here -RAK- */
- void creatures(attack)
- int attack;
- {
- register int i, k;
- register monster_type *m_ptr;
- recall_type *r_ptr;
- int32u notice, rcmove;
- int wake, ignore;
- vtype cdesc;
- #ifdef ATARIST_MWC
- int32u holder;
- #endif
-
- /* Process the monsters */
- for (i = mfptr - 1; i >= MIN_MONIX && !death; i--)
- {
- m_ptr = &m_list[i];
- /* Get rid of an eaten/breathed on monster. Note: Be sure not to
- process this monster. This is necessary because we can't delete
- monsters while scanning the m_list here. */
- if (m_ptr->hp < 0)
- {
- fix2_delete_monster(i);
- continue;
- }
-
- m_ptr->cdis = distance(char_row, char_col,
- (int)m_ptr->fy, (int)m_ptr->fx);
- if (attack) /* Attack is argument passed to CREATURE*/
- {
- k = movement_rate(m_ptr->cspeed);
- if (k <= 0)
- update_mon(i);
- else
- while (k > 0)
- {
- k--;
- wake = FALSE;
- ignore = FALSE;
- rcmove = 0;
- if (m_ptr->ml || (m_ptr->cdis <= c_list[m_ptr->mptr].aaf)
- /* Monsters trapped in rock must be given a turn also,
- so that they will die/dig out immediately. */
- #ifdef ATARIST_MWC
- || ((! (c_list[m_ptr->mptr].cmove & (holder = CM_PHASE)))
- #else
- || ((! (c_list[m_ptr->mptr].cmove & CM_PHASE))
- #endif
- && cave[m_ptr->fy][m_ptr->fx].fval >= MIN_CAVE_WALL))
- {
- if (m_ptr->csleep > 0)
- if (py.flags.aggravate)
- m_ptr->csleep = 0;
- else if ((py.flags.rest == 0 && py.flags.paralysis < 1)
- || (randint(50) == 1))
- {
- notice = randint(1024);
- if (notice*notice*notice <= (1L << (29 - py.misc.stl)))
- {
- m_ptr->csleep -= (100 / m_ptr->cdis);
- if (m_ptr->csleep > 0)
- ignore = TRUE;
- else
- {
- wake = TRUE;
- /* force it to be exactly zero */
- m_ptr->csleep = 0;
- }
- }
- }
- if (m_ptr->stunned != 0)
- {
- /* NOTE: Balrog = 100*100 = 10000, it always
- recovers instantly */
- if (randint(5000) < c_list[m_ptr->mptr].level
- * c_list[m_ptr->mptr].level)
- m_ptr->stunned = 0;
- else
- m_ptr->stunned--;
- if (m_ptr->stunned == 0)
- {
- if (!m_ptr->ml)
- (void) strcpy(cdesc, "It ");
- else
- (void) sprintf(cdesc, "The %s ",
- c_list[m_ptr->mptr].name);
- msg_print(strcat(cdesc,
- "recovers and glares at you."));
- }
- }
- if ((m_ptr->csleep == 0) && (m_ptr->stunned == 0))
- mon_move (i, &rcmove);
- }
-
- update_mon(i);
- if (m_ptr->ml)
- {
- r_ptr = &c_recall[m_ptr->mptr];
- if (wake)
- {
- if (r_ptr->r_wake < MAX_UCHAR)
- r_ptr->r_wake++;
- }
- else if (ignore)
- {
- if (r_ptr->r_ignore < MAX_UCHAR)
- r_ptr->r_ignore++;
- }
- r_ptr->r_cmove |= rcmove;
- }
- }
- }
- else
- update_mon(i);
-
- /* Get rid of an eaten/breathed on monster. This is necessary because
- we can't delete monsters while scanning the m_list here. This
- monster may have been killed during mon_move(). */
- if (m_ptr->hp < 0)
- {
- fix2_delete_monster(i);
- continue;
- }
- }
- /* End processing monsters */
- }
-